Type Deduce - Auto in C++

Syntactic Sugar of auto

在 C++ 中,我们有各种各样的数据类型。我们有 intlongfloatdouble 还有表示字符串的 const char* 等等。我们每次定义一个变量的时候都要带上不同的类型符,好不麻烦。C++ 什么时候能像 python 那样做一些无所谓内置类型的变量定义呢?在 C++11 后,我们有 auto 关键字来帮我们做类似的类型推导。

简单来说,我们在定义类型的时候不需要再考虑它是什么类型了,编译器会帮我们做这些。甚至你可以让它帮你推导自定义的类类型。我们用下面的代码举一些例子:

class MyClass {
public:
    MyClass(int val) : i(val) {}
    int i;
};
auto func(){ // return type is deduced as int type, since C++14
	return 0;
}
int main() {
    int a = 0;
    auto b = a; // b is deduced as int type
    auto c = 0; // c is deduced as int type
    auto d = 3.14; // d is deduced as double type

    auto obj = MyClass{10}; // obj is deduced as MyClass type
    std::cout << "obj.i = " << obj.i << std::endl; // Outputs: obj.i = 10

    return 0;
}

auto 是一个占位符(placeholder),在编译时,编译器会自动推导变量的类型或函数的返回类型。

Type-Safe of Auto

有人可能会觉得 auto 的滥用可能导致变量类型或函数返回类型的混乱。但事实上,当你使用 auto 后,你不需要太担心什么类型推导错误的问题。相反地,一旦你使用 auto,你就应该使用到底。不然就可能导致你不希望看到的问题。我们用一个例子来说明,假设我们有一个 API,我们可以直接用 auto 来与 API 返回的类型相匹配,而不需要担心 API 返回类型的变化,例如:

#include <string>

char* API(int i) {
	char* status;
    if (i == 0) {
	    status = "OKAY";
    } else {
	    status = "false";
    }
	return status;
}

int main() {
    auto status_code = API(1); // status_code is deduced as char*
    std::cout << status_code << std::endl; // Outputs: false
}

在上面的例子中,auto 会将 status_code 推导成 char* 类型。但如果 API 的返回类型变成标准库的 std::string,你仍不需要担心,届时 auto 会推导 status_codestd::string 类型。如果你没有使用 auto,在这种情况下,你的源代码就需要随着 API 返回类型的改变而改变

但另一方面,当你使用 auto 之后,status_code 的类型将对你不可见。为了确定性,你也可以将 auto 去掉。

此外,你需要留意 auto 会忽略引用和 const 。如:

const int& ref = x;
auto a = ref; // a is deduced as int type
const auto&b = ref; // b has the same type as ref

Decltype(auto) Since C++14